// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.patent.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.DepartmentDao;
import com.liuxinlong.modules.dao.PatentDao;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentDepartmentSpecialDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.entity.PatentDepartment;
import com.liuxinlong.modules.entity.PatentDepartmentSpecial;
import com.liuxinlong.modules.entity.UserDepartment;
import com.liuxinlong.modules.patent.service.PatentDepartmentService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 专利部门实现类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2023-09-01
 */
@Service
@Slf4j
public class PatentDepartmentServiceImpl implements PatentDepartmentService {
    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private DepartmentDao departmentDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private PatentDao patentDao;

    @Autowired
    private PatentDepartmentSpecialDao patentDepartmentSpecialDao;

    @Override
    public List<Map<String, Object>> pageDepartmentInfo(Map<String, Object> queryParam) {
        List<PatentDepartment> originList = patentDepartmentDao.pageDepartmentList(queryParam);
        return completeResult(originList, (int) queryParam.get("startNum"));
    }

    @Override
    public int countDepartment(Map<String, Object> queryParam) {
        return patentDepartmentDao.getDepartmentCount(queryParam);
    }

    @Override
    public void addDepartmentInfo(PatentDepartment patentDepartment) {
        patentDepartment.setId(SnowFlake.nextIdStr());
        if (!ObjectUtils.isEmpty(patentDepartmentDao.getDepartmentByName(patentDepartment.getName()))) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同部门名称！");
        }
        if (!ObjectUtils.isEmpty(patentDepartmentDao.getDepartmentBySn(patentDepartment.getSn()))) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同部门编码！");
        }
        List<String> childList = Arrays.asList(patentDepartment.getBranch().split(","));
        if (!ObjectUtils.isEmpty(childList)) {
            for (String childId : childList) {
                PatentDepartment dbInfo = patentDepartmentDao.getDepartmentByChild(childId);
                if (ObjectUtils.isEmpty(dbInfo)) {
                    continue;
                }
                UserDepartment userDepartment = departmentDao.selectById(childId);
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "子部门{ " + userDepartment.getName() + " }已被其他部门{ " + dbInfo.getName() + " }包含！");
            }
        }
        patentDepartmentDao.insert(patentDepartment);
    }

    @Override
    public void updateDepartmentInfo(PatentDepartment patentDepartment) {
        PatentDepartment oldInfo = patentDepartmentDao.getDepartmentByName(patentDepartment.getName());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(oldInfo.getId(), patentDepartment.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同部门名称！");
        }
        oldInfo = patentDepartmentDao.getDepartmentBySn(patentDepartment.getSn());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(oldInfo.getId(), patentDepartment.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同部门编码！");
        }
        List<String> childList = Arrays.asList(patentDepartment.getBranch().split(","));
        if (!ObjectUtils.isEmpty(childList)) {
            for (String childId : childList) {
                PatentDepartment dbInfo = patentDepartmentDao.getDepartmentByChild(childId);
                if (ObjectUtils.isEmpty(dbInfo) || StringUtils.equals(dbInfo.getId(), patentDepartment.getId())) {
                    continue;
                }
                UserDepartment userDepartment = departmentDao.selectById(childId);
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "子部门{ " + userDepartment.getName() + " }已被其他部门{ " + dbInfo.getName() + " }包含！");
            }
        }
        patentDepartmentDao.updateById(patentDepartment);
    }

    @Override
    public void deleteDepartmentInfo(String id) {
        if (patentDao.countDepartmentPatent(id) > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "部门存在专利，不可删除！");
        }
        patentDepartmentDao.deleteById(id);
    }

    @Override
    public ImportResp importDepartments(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
//                UserDepartment UserDepartment = covertToBean(record);
                return false;
//				try {
//					UserDepartmentDao.addDetail(UserDepartment);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }


            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入部门数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入部门数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap<>();
                    item.put("sort", sort);
                    item.put("name", failRecord[1]);
                    item.put("sn", failRecord[2]);
                    item.put("manage", failRecord[3]);
                    item.put("branch", failRecord[4]);
                    item.put("remark", failRecord[5]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddDepartment(List<PatentDepartment> dataList) {
        List<Map> failedList = new ArrayList<>();
        List<PatentDepartment> importList = new ArrayList<>();
        Map<String, Map<String, String>> departmentNameMap = departmentDao.getDepartmentMapByName();
        Map<String, Map<String, String>> userSnMap = userDao.getUserMapBySn();
        Map<String, Map<String, String>> pDepartmentSnMap = patentDepartmentDao.getDepartmentMapBySn();
        int sort = 1;
        for (PatentDepartment patentDepartment : dataList) {
            PatentDepartment depInfo = new PatentDepartment();
            depInfo.setName(patentDepartment.getName());
            depInfo.setSn(patentDepartment.getSn());
            depInfo.setRemark(patentDepartment.getRemark());
            if (StringUtils.isEmpty(patentDepartment.getSn()) || pDepartmentSnMap.containsKey(patentDepartment.getSn())) {
                Map item = ObjectUtils.object2Map(patentDepartment);
                item.put("sort", sort);
                item.put("message", "部门编码为空或部门编码已存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            // 部门经理匹配系统内用户
            List<String> manageUserList = Arrays.asList(patentDepartment.getManage().split("-"));
            if (manageUserList.size() != 2) {
                Map item = ObjectUtils.object2Map(patentDepartment);
                item.put("sort", sort);
                item.put("message", "部门经理不存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            if (!userSnMap.containsKey(manageUserList.get(1))) {
                Map item = ObjectUtils.object2Map(patentDepartment);
                item.put("sort", sort);
                item.put("message", "部门经理不存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            depInfo.setManage(userSnMap.get(manageUserList.get(1)).get("id"));
            // 子部门匹配系统内部门
            List<String> childNameList = Arrays.asList(patentDepartment.getBranch().split(","));
            boolean childError = false;
            List<String> childList = new ArrayList<>(childNameList.size());
            for (String item : childNameList) {
                if (!departmentNameMap.containsKey(item.trim())) {
                    childError = true;
                    break;
                }
                Map<String, String> childDep = departmentNameMap.get(item.trim());
                childList.add(childDep.get("id"));
            }
            if (childError) {
                Map item = ObjectUtils.object2Map(patentDepartment);
                item.put("sort", sort);
                item.put("message", "子部门不存在！");
                failedList.add(item);
                sort++;
                continue;
            }
            depInfo.setBranch(StringUtils.strip(childList.toString(), "[]"));
            depInfo.setId(SnowFlake.nextIdStr());
            importList.add(depInfo);
        }
        if (!importList.isEmpty()) {
            patentDepartmentDao.insertBatch(importList);
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() : ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setRetMessage(failedList.size() > 0 ? "导入专利部门信息成功" : "导入专利部门信息成功");
        resp.setFailedList(failedList);
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(importList.size());
        resp.setFailedTotal(failedList.size());
        return resp;
    }

    @Override
    public void exportPatentDepartment(HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("专利部门信息导出excel.xlsx");
        List<PatentDepartment> patentDepartmentList = patentDepartmentDao.getDepartmentList();
        String[] head = {"序号", "部门名称", "部门编码", "部门经理", "子部门", "备注"};
        data.setHead(head);
        String[][] dataList = new String[patentDepartmentList.size()][head.length];
        int index = 0;
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        for (PatentDepartment item : patentDepartmentList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getName();
            dataList[index][2] = item.getSn();
            dataList[index][3] = userMap.containsKey(item.getManage()) ? userMap.get(item.getManage()).get("name") + "-" + userMap.get(item.getManage()).get("sn") : "";
            List<String> branchDep = Arrays.asList(item.getBranch().split(","));
            List<String> branchList = new ArrayList<>();
            for (String dep : branchDep) {
                if (departmentMap.containsKey(dep)) {
                    branchList.add(departmentMap.get(dep).get("name"));
                }
            }
            dataList[index][4] = StringUtils.strip(branchList.toString(), "[]");
            dataList[index][5] = item.getRemark();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public List<Map<String, Object>> pageDepartmentSpecialInfo(Map<String, Object> queryParam) {
        List<PatentDepartmentSpecial> specialList = patentDepartmentSpecialDao.pageDepartmentSpecialList(queryParam);
        List<Map<String, Object>> dataList = new ArrayList<>();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String, Map<String, String>> depMap = patentDepartmentDao.getDepartmentMap();
        int sort = (int) queryParam.get("startNum") + 1;
        for (PatentDepartmentSpecial special : specialList) {
            Map<String, Object> item = ObjectUtils.object2Map(special);
            item.put("sort", sort);
            item.put("userName", userMap.containsKey(special.getSpecialUser()) ? userMap.get(special.getSpecialUser()).get("name") : "");
            List<String> branchList = Arrays.asList(special.getBranch().split(","));
            List<String> depList = new ArrayList<>(branchList.size());
            for (String branch : branchList) {
                if (depMap.containsKey(branch)) {
                    depList.add(depMap.get(branch).get("name"));
                    continue;
                }
            }
            item.put("department", StringUtils.strip(depList.toString(), "[]"));
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int countDepartmentSpecial(Map<String, Object> queryParam) {
        return patentDepartmentSpecialDao.getDepartmentSpecialCount(queryParam);
    }

    @Override
    public void addDepartmentSpecialInfo(PatentDepartmentSpecial patentDepartmentSpecial) {
        patentDepartmentSpecial.setId(SnowFlake.nextIdStr());
        PatentDepartmentSpecial oldInfo = patentDepartmentSpecialDao.getDepartmentSpecialById(patentDepartmentSpecial.getSpecialUser());
        if (!ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户已配置，请修改！");
        }
        patentDepartmentSpecialDao.insert(patentDepartmentSpecial);
    }

    @Override
    public void updateDepartmentSpecialInfo(PatentDepartmentSpecial patentDepartmentSpecial) {
        PatentDepartmentSpecial oldInfo = patentDepartmentSpecialDao.getDepartmentSpecialById(patentDepartmentSpecial.getSpecialUser());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(oldInfo.getId(), patentDepartmentSpecial.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户已配置，请修改！");
        }
        patentDepartmentSpecialDao.updateById(patentDepartmentSpecial);
    }

    @Override
    public void deleteDepartmentSpecialInfo(String id) {
        PatentDepartmentSpecial oldInfo = patentDepartmentSpecialDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户配置不存在！");
        }
        patentDepartmentSpecialDao.deleteById(id);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始值
     * @return 补全后数据
     */
    private List<Map<String, Object>> completeResult(List<PatentDepartment> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        int sort = startNum + 1;
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        for (PatentDepartment department : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(department);
            map.put("sort", sort);
            map.put("manageName", userMap.containsKey(department.getManage()) ? userMap.get(department.getManage()).get("name") : "-");
            if (!StringUtils.isEmpty(department.getDutyUser())) {
                List<String> dutyList = Arrays.asList(department.getDutyUser().split(","));
                List<String> dutyUserNameList = new ArrayList<>();
                for (String duty: dutyList) {
                    dutyUserNameList.add(userMap.containsKey(duty) ? userMap.get(duty).get("name") : "-");
                }
                map.put("dutyUserName", StringUtils.strip(dutyUserNameList.toString(), "[]").replaceAll(" +", ""));
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("部门名称不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 50) {
                addRowError("部门名称长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("部门编码不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 20) {
                addRowError("部门编码长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[3].trim())) {
            addRowError("部门经理不能为空", rowErrors);
        } else {
            if (record[3].trim().length() > 20) {
                addRowError("部门经理名称长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("部门经理不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 20000) {
                addRowError("子部门长度不能超过20000", rowErrors);
            }
        }
        if (record.length > 5 && !StringUtils.isEmpty(record[5].trim())) {
            if (record[5].trim().length() > 200) {
                addRowError("描述长度不能超过200", rowErrors);
            }
        }

        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

}
